using System;
using System.Windows.Forms;
using ShadeTree.Binding.Drivers;
using ShadeTree.Binding.Stylers;

namespace ShadeTree.Binding.Configuration
{
    public abstract class ScreenElementExpression<EXPRESSIONTYPE>
    {
        private readonly IScreenElement _element;

        public ScreenElementExpression(IScreenElement element)
        {
            _element = element;
        }

        protected abstract EXPRESSIONTYPE thisExpression();

        public EXPRESSIONTYPE WithAlias(string alias)
        {
            _element.Alias = alias;
            return thisExpression();
        }

        public EXPRESSIONTYPE WithLabel(Label label)
        {
            Styler.Default.ApplyStyle(label);

            _element.Label = ControlDriverFactory.GetDriver(label);
            return thisExpression();
        }

        public EXPRESSIONTYPE WithLabel(System.Windows.Controls.Label label)
        {
            Styler.Default.ApplyStyle(label);

            _element.Label = ControlDriverFactory.GetDriver(label);
            return thisExpression();
        }

        public EXPRESSIONTYPE OnChange(Action action)
        {
            ((IBoundScreenElement) _element).RegisterChangeHandler(action);
            return thisExpression();
        }

        public EXPRESSIONTYPE OnLostFocus(Action action)
        {
            ((IBoundScreenElement) _element).RegisterLostFocusHandler(action);
            return thisExpression();
        }

        public EXPRESSIONTYPE RememberLastChoice()
        {
            ((IBoundScreenElement) _element).RememberLastChoice();
            return thisExpression();
        }

        public EXPRESSIONTYPE RebindOnChange()
        {
            ((IBoundScreenElement) _element).RebindAllOnChange();

            return thisExpression();
        }

        public EXPRESSIONTYPE AsReadOnly()
        {
            _element.ActivationMode = ActivationMode.ReadOnly;
            return thisExpression();
        }

        public EXPRESSIONTYPE WatchWith(IWatcher watcher)
        {
            watcher.Watch(_element);
            return thisExpression();
        }

        public EXPRESSIONTYPE WatchWith<T>() where T : IWatcher, new()
        {
            return WatchWith(new T());
        }
    }

    public class BasicElementExpression : ScreenElementExpression<BasicElementExpression>
    {
        public BasicElementExpression(IScreenElement element) : base(element)
        {
        }


        protected override BasicElementExpression thisExpression()
        {
            return this;
        }
    }
}